package com.luntan.util.web;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.Vector;

/*
 * StringUtil.java
 *
 * Copyright 1999, 2000, 2001 Jcorporate Ltd.
 */
/**
 * Utilities for manipulations of strings
 *
 * @version $Revision: 1.9 $ $Date: 2002/10/30 23:38:12 $
 * @author Michael Nash
 */
public final class StringUtil {

    public static final String EMPTY_STRING = "";

    /**
     * Constructor
     */
    public StringUtil() {
        super();
    } /* StringUtil() */


    /**
     * Parses a boolean string to return a boolean value
     *
     * @param theString
     *            The string to parse
     * @return True or False depending of the contents of the string.
     */
    public static boolean toBoolean(String theString) {
        if (theString == null) {
            return false;
        }

        theString = theString.trim();

        if (theString.equalsIgnoreCase("y")
                || theString.equalsIgnoreCase("yes")
                || theString.equalsIgnoreCase("true")
                || theString.equalsIgnoreCase("1")) {
            return true;
        }

        return false;
    }

    /**
     * Make sure a string is not null. This is a convenience method, but it is
     * not necessarily recommended if you do a lot of processing for theMessage
     * parameter. It is recommended that you assertNotBlank, catch
     * IllegalArgumentException and then throw an appropriate exception with
     * your message.
     *
     * @param theString
     *            Any string, possibly null
     * @param theMessage
     *            The error message to use if the argument is not null.
     */
    public static final void assertNotBlank(String theString, String theMessage) {
        if (theString == null) {
            throw new IllegalArgumentException("Null argument not allowed: "
                    + theMessage);
        }
        if (theString.trim().equals(EMPTY_STRING)) {
            throw new IllegalArgumentException("Blank argument not allowed: "
                    + theMessage);
        }
    } /* assertNotBlank(String, String) */


    /**
     * Make sure a string is not null.
     *
     * @param theString
     *            Any string, possibly null
     * @return An empty string if the original was null, else the original
     */
    public static final String notNull(String theString) {
        if (theString == null) {
            return EMPTY_STRING;
        }

        return theString;
    } /* notNull(String) */


    /**
     * Throws an exception if theString can't be mapped to a boolean value.
     *
     * @param theString
     *            the string to check
     * @param theMessage
     *            the message to have in the IllegalArgumentException if the
     *            conditions aren't met.
     */
    public static final void assertBoolean(String theString, String theMessage) {
        assertNotBlank(theString, theMessage);

        if (!(theString.equalsIgnoreCase("yes")
                || theString.equalsIgnoreCase("true")
                || theString.equalsIgnoreCase("no")
                || theString.equalsIgnoreCase("false")
                || theString.equalsIgnoreCase("y") || theString.equalsIgnoreCase("n"))) {
            throw new IllegalArgumentException(theMessage);
        }
    }

    /**
     * This method is useful for creating lists that use letters instead of
     * numbers, such as a, b, c, d...instead of 1, 2, 3, 4. Valid numbers are
     * from 1 to 26, corresponding to the 26 letters of the alphabet. By
     * default, the letter is returned as a lowercase, but if the boolean
     * upperCaseFlag is true, the letter will be returned as an uppercase.
     * Creation date: (5/11/00 12:52:23 PM)
     *
     * @author: Adam Rossi
     *
     * @return java.lang.String
     * @param number
     *            The number to convert
     * @param upperCaseFlag
     *            True if you want the final data to be uppercase
     * @throws Exception
     */
    public static String numberToLetter(int number, boolean upperCaseFlag)
            throws Exception {

        // add nine to bring the numbers into the right range (in java, a= 10, z
        // = 35)
        if (number < 1 || number > 26) {
            throw new Exception("The number is out of the proper range (1 to "
                    + "26) to be converted to a letter.");
        }

        int modnumber = number + 9;
        char thechar = Character.forDigit(modnumber, 36);

        if (upperCaseFlag) {
            thechar = Character.toUpperCase(thechar);
        }

        return "" + thechar;
    } /* numberToLetter(int, boolean) */


    /**
     * replace substrings within string.
     *
     * @param s
     *            The string to work with
     * @param sub
     *            The string to substitude the occurances of
     * @param with
     *            The string to replace with
     * @return A processed java.util.String
     */
    public static String replace(String s, String sub, String with) {
        int c = 0;
        int i = s.indexOf(sub, c);

        if (i == -1) {
            return s;
        }

        FastStringBuffer buf = new FastStringBuffer(s.length() + with.length());

        do {
            buf.append(s.substring(c, i));
            buf.append(with);
            c = i + sub.length();
        } while ((i = s.indexOf(sub, c)) != -1);

        if (c < s.length()) {
            buf.append(s.substring(c, s.length()));
        }

        return buf.toString();
    } /* replace(String, String, String) */


    /**
     * Formats the string to an XML/XHTML escaped character. Useful for &'s, etc
     *
     * @param s
     *            the String to format
     * @return The escaped formatted String.
     * @see org.apache.xml.serialize.BaseMarkupSerializer for example of
     *      original code.
     */
    public static String xmlEscape(String s) {
        int length = s.length();
        FastStringBuffer fsb = new FastStringBuffer(length);

        for (int i = 0; i < length; i++) {
            fsb = printEscaped(s.charAt(i), fsb);
        }

        return fsb.toString();
    }

    /**
     * Formats a particular character to something workable in xml Helper to
     * xmlEscape()
     *
     * @param ch
     *            the character to print.
     * @param fsb
     *            The FastStringBuffer to add this to.
     * @return a FastStringBuffer that is modified
     */
    protected static FastStringBuffer printEscaped(char ch, FastStringBuffer fsb) {
        String charRef;

        // If there is a suitable entity reference for this
        // character, print it. The list of available entity
        // references is almost but not identical between
        // XML and HTML.
        charRef = getEntityRef(ch);

        if (charRef != null) {
            fsb.append('&');
            fsb.append(charRef);
            fsb.append(';');

            // ch<0xFF == isPrintable()
        } else if ((ch >= ' ' && ch < 0xFF && ch != 0xF7) || ch == '\n'
                || ch == '\r' || ch == '\t') {

            // If the character is not printable, print as character reference.
            // Non printables are below ASCII space but not tab or line
            // terminator, ASCII delete, or above a certain Unicode threshold.
            if (ch < 0x10000) {
                fsb.append(ch);
            } else {
                fsb.append((char) ((((int) ch - 0x10000) >> 10) + 0xd800));
                fsb.append((char) ((((int) ch - 0x10000) & 0x3ff) + 0xdc00));
            }
        } else {
            fsb.append("&#x");
            fsb.append(Integer.toHexString(ch));
            fsb.append(';');
        }

        return fsb;
    }

    /**
     * Helper to xmlEscape()
     *
     * @param ch
     *            the character to escape
     * @return A modified string representing the tanlation of the character or
     *         null if there is no translation for it.
     */
    protected static String getEntityRef(int ch) {

        // Encode special XML characters into the equivalent character
        // references.
        // These five are defined by default for all XML documents.
        switch (ch) {
            case '<':
                return "lt";

            case '>':
                return "gt";

            case '"':
                return "quot";

            case '\'':
                return "apos";

            case '&':
                return "amp";
        }

        return null;
    }

    /**
     * HTML code for ellipses (3 dots, like '...' as one character) used for
     * appending to a truncate() line if necessary
     */
    public static String ELLIPSES = "&#133";

    /**
     * truncate a string at the given length if necessary, adding an ellipses at
     * the end if truncation occurred; uses ELLIPSES static String from this
     * class
     *
     * @param str
     *            The string to process
     * @param len
     *            The maximum length to process the string to.
     * @return the appropriately trimmed string.
     */
    public static String truncate(String str, int len) {
        String result = str;
        if (str.length() > len) {
            result = str.substring(0, len) + ELLIPSES;
        }
        return result;
    }

    /**
     * Map accent characters with equivalent without accent.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @return Hashtable Character mapping table.
     */
    public static Hashtable characterMap() {
        Hashtable characterMap = new Hashtable();

        characterMap.put(new Character('\uFFFD'), new Character('a'));
        characterMap.put(new Character('\uFFFD'), new Character('a'));
        characterMap.put(new Character('\uFFFD'), new Character('a'));
        characterMap.put(new Character('\uFFFD'), new Character('a'));
        characterMap.put(new Character('\uFFFD'), new Character('A'));
        characterMap.put(new Character('\uFFFD'), new Character('A'));
        characterMap.put(new Character('\uFFFD'), new Character('A'));
        characterMap.put(new Character('\uFFFD'), new Character('A'));
        characterMap.put(new Character('\uFFFD'), new Character('e'));
        characterMap.put(new Character('\uFFFD'), new Character('e'));
        characterMap.put(new Character('\uFFFD'), new Character('e'));
        characterMap.put(new Character('\uFFFD'), new Character('e'));
        characterMap.put(new Character('\uFFFD'), new Character('E'));
        characterMap.put(new Character('\uFFFD'), new Character('E'));
        characterMap.put(new Character('\uFFFD'), new Character('E'));
        characterMap.put(new Character('\uFFFD'), new Character('E'));
        characterMap.put(new Character('\uFFFD'), new Character('i'));
        characterMap.put(new Character('\uFFFD'), new Character('i'));
        characterMap.put(new Character('\uFFFD'), new Character('I'));
        characterMap.put(new Character('\uFFFD'), new Character('I'));
        characterMap.put(new Character('\uFFFD'), new Character('o'));
        characterMap.put(new Character('\uFFFD'), new Character('o'));
        characterMap.put(new Character('\uFFFD'), new Character('O'));
        characterMap.put(new Character('\uFFFD'), new Character('O'));
        characterMap.put(new Character('\uFFFD'), new Character('u'));
        characterMap.put(new Character('\uFFFD'), new Character('u'));
        characterMap.put(new Character('\uFFFD'), new Character('U'));
        characterMap.put(new Character('\uFFFD'), new Character('U'));
        characterMap.put(new Character('\uFFFD'), new Character('c'));
        characterMap.put(new Character('\uFFFD'), new Character('C'));

        return characterMap;
    }

    /**
     * Remove from the parameter the accent characters and return the remain
     * string or null if empty
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param s
     *            the string to remove the accent characters
     * @return String
     */
    public static String removeAccents(String s) {
        String out = null;
        if (s != null) {
            Hashtable charRemove = characterMap();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < s.length(); i++) {
                Character c = new Character(s.charAt(i));
                if (charRemove.containsKey(c)) {
                    c = (Character) charRemove.get(c);
                }
                sb.append(c.charValue());
            }
            out = sb.toString();
        }
        return out;
    }

    /**
     * Replace all comma by dot
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String to change
     * @return String The result of substitution
     */
    public static String convertCommaToDot(String str) {
        return str.replace(',', '.');
    }

    /**
     * Compare 2 decimals string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param decim1
     *            First string to compare
     * @param decim2
     *            Second string to compare
     * @throws ParseException
     *             if wrong parameters.
     * @return int return 1 if decim1 > decim2<BR>
     *         retourne 0 if decim1 == decim2<BR>
     *         return -1 if decim1 < decim2
     */
    public static int compareDecimals(String decim1, String decim2)
            throws ParseException {
        BigDecimal dec1 = new BigDecimal(decim1);
        BigDecimal dec2 = new BigDecimal(decim2);
        return dec1.compareTo(dec2);
    }

    /**
     * Compare 2 integers string.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param int1
     *            first string to compare
     * @param int2
     *            second string to compare
     * @throws ParseException
     *             if wrong parameters.
     * @return int return 1 if decim1 > decim2<BR>
     *         return 0 if decim1 == decim2<BR>
     *         return -1 if decim1 < decim2
     */
    public static int compareIntegers(String int1, String int2)
            throws ParseException {
        BigInteger dec1 = new BigInteger(int1);
        BigInteger dec2 = new BigInteger(int2);
        return dec1.compareTo(dec2);
    }

    /**
     * Check if string is alphanumeric or not.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            String to check.
     * @return boolean true if alphanumeric, false if not.
     */
    public static boolean isAlphaNumeric(String s) {
        return isAlphaNumeric(s, "");
    }

    /**
     * Check if string is alphanumeric with addons chararcters or not.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            string to check
     * @param otherChars
     *            extra characters to check with
     * @return boolean true if parameter string contains only alpha numerics,<BR>
     *         plus addons characters and false if not.
     */
    public static boolean isAlphaNumeric(String str, String otherChars) {
        String alphaNum = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                + otherChars;
        for (int i = 0; i < str.length(); i++) {
            if (alphaNum.indexOf(str.charAt(i)) == -1) {
                return false;
            }
        }
        return true;
    }

    /**
     * Check if decimal number
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            string to check.
     * @return boolean true if the value is decimal number false if not
     */
    public static boolean isDecimal(String s) {
        try {
            new BigDecimal(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Check if string pass is a vlaid email address
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param email
     *            string to check
     * @return int 0 if valid address, 1 more than 2 tokens (".", "@")<BR>
     *         and 2 if the second token is not "." .
     */
    public static int isEmail(String email) {
        StringTokenizer st = new StringTokenizer(email, "@");

        if (st.countTokens() != 2) {
            return 1;
        }

        st.nextToken();
        if (st.nextToken().indexOf(".") == -1) {
            return 2;
        }

        return 0;
    }

    /**
     * Check if integer string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            string to check
     * @return boolean true if all characters is digit
     */
    public static boolean isInteger(String str) {
        try {
            new BigInteger(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Check if number
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            to check
     * @return boolean
     */
    public static boolean isNumber(String str) {
        try {
            double number = Double.parseDouble(str);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    /**
     * Check French company siren number.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param siren
     *            the company number
     * @return boolean true if ok.
     */
    public static boolean isSiren(String siren) {
        StringBuffer temp = new StringBuffer("");
        int value = 0;

        // Check if numeric digit.
        try {
            Double.parseDouble(siren);
        } catch (NumberFormatException nbe) {
            return false;
        }

        // string length must be 9
        if (siren.length() != 9) {
            return false;
        }

        //
        for (int i = 0; i < 9; i++) {
            int n = Integer.parseInt(siren.substring(i, i + 1))
                    * (((i % 2) != 0) ? 2 : 1);
            temp.append(n);
        }

        // sum of all digits
        for (int i = 0; i < (temp.length()); i++) {
            value += Integer.parseInt(temp.substring(i, i + 1));
        }

        // value must divide by 10
        if ((value % 10) != 0) {
            return false;
        }

        return true;
    }

    /**
     * Check French company siret number
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param siret
     *            The siret number
     * @return boolean true if equivalent to siret number false if not.
     */
    public static boolean isSiret(String siret) {
        // Check the length
        if (siret.length() != 14) {
            return false;
        }

        //
        try {
            Double.parseDouble(siret);
            return isSiren(siret.substring(0, 9));
        } catch (NumberFormatException nfe) {
            return false;
        }
    }

    /**
     * Return empty string if parameter is null
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            the parameter to check
     * @return String return the parameter if empty or if the string == null
     */
    public static String nullToEmpty(String s) {
        if (s == null) {
            return "";
        } else {
            return s;
        }
    }

    /**
     * Reformat string by converting "," by "."
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            string to reformat
     * @return String return reformatted string.
     */
    public static String reformatDecimalString(String str) {
        // replace all ',' by '.'
        str = str.replace(',', '.');
        try {
            Double.parseDouble(str);
            return str;
        } catch (NumberFormatException nbe) {
            return "";
        }
    }

    /**
     * Replace all dots byt comma
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            string to change
     * @return String reformatted
     */
    public static String convertDotToComma(String str) {
        return str.replace('.', ',');
    }

    /**
     * Replace all occurences of key by value in text.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param text
     *            string in
     * @param key
     *            occurence to replace
     * @param value
     *            string to use
     * @return String with the replace value
     */
    public static String replaceAll(String text, String key, String value) {
        String buffer = text;
        if (buffer != null && key != null && value != null) {
            int length = key.length();
            for (int start = buffer.indexOf(key); start != -1; start = buffer.indexOf(key, start + value.length())) {
                buffer = buffer.substring(0, start) + value
                        + buffer.substring(start + length);
            }
        }
        return buffer;
    }

    /**
     * Substituate once str1 by str2 in text Commentaire Anglais
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param text
     *            search and replace in
     * @param str1
     *            to search for
     * @param str2
     *            to replace with
     *
     * @return String replaced
     */
    static public String replaceStringOnce(String text, String str1, String str2) {
        return replaceString(text, str1, str2, 1);
    }

    /**
     * Substituate all occurence of str1 by str2 in text
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     *
     * @param text
     *            search and replace in
     * @param str1
     *            search for
     * @param str2
     *            replace with
     *
     * @return String with all values replaced
     */
    static public String replaceString(String text, String str1, String str2) {
        return replaceString(text, str1, str2, -1);
    }

    /**
     * Replace n occurences of str1 in text by str2. if n = -1 all occurrences
     * are replaced
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param text
     *            search and replace in
     * @param str1
     *            search for
     * @param str2
     *            replace with
     * @param max
     *            int values of occrrences to replace
     * @return String replaced
     */
    static public String replaceString(String text, String str1, String str2,
            int max) {
        if (text == null) {
            return null;
        }

        StringBuffer buffer = new StringBuffer(text.length());
        int start = 0;
        int end = 0;
        while ((end = text.indexOf(str1, start)) != -1) {
            buffer.append(text.substring(start, end)).append(str2);
            start = end + str1.length();
            if (--max == 0) {
                break;
            }
        }
        buffer.append(text.substring(start));
        return buffer.toString();
    }

    /**
     * Convert string to list
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            String comma delimited string to format
     * @return List
     */
    public static List string2List(String s) {
        return string2List(s, ",");
    }

    /**
     * Convert string to list using sep separator to divide
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            String comma delimited string to format
     * @param sep
     *            a string containing the seprator characters
     *
     * @return List
     */
    public static List string2List(String s, String sep) {
        return string2List(s, sep, s != null ? s.length() : Integer.MAX_VALUE);
    }

    /**
     * Convert string to list using sep separator to divide
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param s
     *            String comma delimited string to format
     * @param sep
     *            a string containing the seprator characters
     * @param maxSize
     *            the maximum size of the list
     *
     * @return List
     */
    public static List string2List(String s, String sep, int maxSize) {
        List l = null;
        if (s != null) {
            l = new Vector();
            for (int i = 0; i < maxSize;) {
                int index = s.indexOf(sep, i);
                String token;
                if (index != -1) {
                    token = s.substring(i, index);
                } else {
                    token = s.substring(i);
                }
                if (token.length() > 0 && !token.equals(sep)) {
                    l.add(token.trim());
                }
                i += token.length() + sep.length();
            }
        }
        return l;
    }

    /**
     * convert the first character of string in lower case
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     *
     * @param str
     *            String to un-upper case the first character
     * @return String
     */
    static public String unUpperFirstChar(String str) {
        FastStringBuffer fsb = null;
        ;
        try {
            fsb = FastStringBuffer.getInstance();
            fsb.append(Character.toLowerCase(str.charAt(0)));
            fsb.append(str.substring(1));
            return fsb.toString();
        } finally {
            if (fsb != null) {
                fsb.release();
            }
        }
    }

    /**
     * convert the first character of the string upper case
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String to make the first character upper.
     * @return String
     */
    static public String upperFirstChar(String str) {

        FastStringBuffer fsb = FastStringBuffer.getInstance();
        try {
            fsb.append(Character.toTitleCase(str.charAt(0)));
            fsb.append(str.substring(1));
            return fsb.toString();
        } finally {
            fsb.release();
        }

        // return "" + Character.toTitleCase(str.charAt(0)) + str.substring(1);
    }

    /**
     * Repeat str n time to format another string.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String to repeat
     * @param n
     *            int n repeat
     *
     * @return String
     */
    static public String repeatString(String str, int n) {
        FastStringBuffer buffer = FastStringBuffer.getInstance();
        try {
            // FastStringBuffer is preallocated for 1K, so we may not
            // need to do any memory allocation here.
            int val = n * str.length();
            if (val > buffer.capacity()) {
                buffer.ensureCapacity(val);
            }
            // StringBuffer buffer = new StringBuffer(n * str.length());
            for (int i = 0; i < n; i++) {
                buffer.append(str);
            }
            return buffer.toString();
        } finally {
            buffer.release();
        }
    }

    /**
     * enclosed the string with padding character. Space is padding character
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String str string to center padding
     * @param n
     *            int n size of the new string
     *
     * @return String Result
     */
    static public String centerPad(String str, int n) {
        return centerPad(str, n, " ");
    }

    /**
     * Enclosed the string with padding character
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     *
     * @param str
     *            String str string to pad with
     * @param n
     *            int n size of the final string
     * @param delim
     *            String delim padding character
     *
     * @return String result of the center padding
     */
    static public String centerPad(String str, int n, String delim) {
        int sz = str.length();
        int p = n - sz;
        if (p < 1) {
            return str;
        }
        str = leftPad(str, sz + p / 2, delim);
        str = rightPad(str, n, delim);
        return str;
    }

    /**
     * Right padding with delimiter
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String
     * @param n
     *            int size of the final string
     * @param delim
     *            padding character
     *
     * @return String padding string
     */
    static public String rightPad(String str, int n, String delim) {
        int sz = str.length();
        n = (n - sz) / delim.length();
        if (n > 0) {
            str += repeatString(delim, n);
        }
        return str;
    }

    /**
     * Right padding delimiter is space
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String
     * @param n
     *            int size of the new string
     *
     * @return String
     */
    static public String rightPad(String str, int n) {
        return rightPad(str, n, " ");
    }

    /**
     * Left padding padding character is space
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String
     * @param n
     *            int size of the new string
     *
     * @return String
     */
    static public String leftPad(String str, int n) {
        return leftPad(str, n, " ");
    }

    /**
     * Left padding
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     *
     * @param str
     *            String
     * @param n
     *            int size of the new string
     * @param delim
     *            padding character
     *
     * @return String result
     */
    static public String leftPad(String str, int n, String delim) {
        int sz = str.length();
        n = (n - sz) / delim.length();
        if (n > 0) {
            str = repeatString(delim, n) + str;
        }
        return str;
    }

    /**
     * Reverse the String.
     *
     * @param str
     *            the String to reverse.
     * @return a reversed string
     */
    static public String reverseString(String str) {
        FastStringBuffer fsb = FastStringBuffer.getInstance();
        try {
            fsb.append(str);
            return fsb.reverse().toString();
        } finally {
            fsb.release();
        }
    }

    /**
     * Reverse the character case in the string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param str
     *            String
     *
     * @return String
     */
    static public String swapCase(String str) {
        int sz = str.length();
        FastStringBuffer buffer = FastStringBuffer.getInstance();
        // StringBuffer buffer = new StringBuffer(sz);
        try {
            if (sz > buffer.capacity()) {
                buffer.ensureCapacity(sz);
            }
            boolean whiteSpace = false;
            char ch = 0;
            char tmp = 0;
            for (int i = 0; i < sz; i++) {
                ch = str.charAt(i);
                if (Character.isUpperCase(ch)) {
                    tmp = Character.toLowerCase(ch);
                } else if (Character.isTitleCase(ch)) {
                    tmp = Character.toLowerCase(ch);
                } else if (Character.isLowerCase(ch)) {
                    if (whiteSpace) {
                        tmp = Character.toTitleCase(ch);
                    } else {
                        tmp = Character.toUpperCase(ch);
                    }
                }
                buffer.append(tmp);
                whiteSpace = Character.isWhitespace(ch);
            }
            return buffer.toString();
        } finally {
            buffer.release();
        }
    }

    /**
     * Create a random string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     *
     * @param count
     *            size of string.
     * @return randomly generated string of size count
     */
    static public String random(int count) {
        return random(count, false, false);
    }

    /**
     * Create a random Ascii String
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @return randomly generated string of size count
     */
    static public String randomAscii(int count) {
        return random(count, 32, 127, false, false);
    }

    /**
     * Create a random character only string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            size of string
     * @return randomly generated string of size count
     */
    static public String randomAlphabetic(int count) {
        return random(count, true, false);
    }

    /**
     * Create a random alpha numeric string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @return randomly generated string of size count
     */
    static public String randomAlphanumeric(int count) {
        return random(count, true, true);
    }

    /**
     * Create a random numeric string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the final string
     * @return randomly generated string of size count
     */
    static public String randomNumeric(int count) {
        return random(count, false, true);
    }

    /**
     * Create a random numeric string where you have control over size, and
     * whether you want letters, numbers, or both.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @param letters
     *            true if you want letters included
     * @param numbers
     *            true if you want numbers included
     * @return randomly generated string of size count
     */
    static public String random(int count, boolean letters, boolean numbers) {
        return random(count, 0, 0, letters, numbers);
    }

    /**
     * Create a random numeric string where you have control over size, and
     * whether you want letters, numbers, as well as ANSI minimum and maximum
     * values of the characters.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @param start
     *            int minimum 'value' of the character
     * @param end
     *            maximum 'value' of the character
     * @param letters
     *            true if you want letters included
     * @param numbers
     *            true if you want numbers included
     * @return randomly generated string of size count
     */
    static public String random(int count, int start, int end, boolean letters,
            boolean numbers) {
        return random(count, start, end, letters, numbers, null);
    }

    /**
     * Create a random numeric string where you have control over size, and
     * whether you want letters, numbers, as well as ANSI minimum and maximum
     * values of the characters.
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @param start
     *            int minimum 'value' of the character
     * @param end
     *            maximum 'value' of the character
     * @param letters
     *            true if you want letters included
     * @param numbers
     *            true if you want numbers included
     * @param set
     *            the set of possible characters that you're willing to let the
     *            string contain. may be null if all values are open.
     * @return randomly generated string of size count
     * @todo make this cryptographically string
     */
    static public String random(int count, int start, int end, boolean letters,
            boolean numbers, char[] set) {
        if ((start == 0) && (end == 0)) {
            end = (int) 'z';
            start = (int) ' ';
            if (!letters && !numbers) {
                start = 0;
                end = Integer.MAX_VALUE;
            }
        }
        Random rnd = new Random();
        // StringBuffer buffer = new StringBuffer();
        FastStringBuffer buffer = FastStringBuffer.getInstance();
        try {
            int gap = end - start;
            while (count-- != 0) {
                char ch;
                if (set == null) {
                    ch = (char) (rnd.nextInt(gap) + start);
                } else {
                    ch = set[rnd.nextInt(gap) + start];
                }
                if ((letters && numbers && Character.isLetterOrDigit(ch))
                        || (letters && Character.isLetter(ch))
                        || (numbers && Character.isDigit(ch))
                        || (!letters && !numbers)) {
                    buffer.append(ch);
                } else {
                    count++;
                }
            }
            return buffer.toString();
        } finally {
            buffer.release();
        }
    }

    /**
     * Create a random string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @param set
     *            the set of characters that are allowed
     * @return randomly generated string of size count
     */
    static public String random(int count, String set) {
        return random(count, set.toCharArray());
    }

    /**
     * Create a random string
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param count
     *            the size of the string
     * @param set
     *            the set of characters that are allowed
     * @return randomly generated string of size count
     */
    static public String random(int count, char[] set) {
        return random(count, 0, set.length - 1, false, false, set);
    }

    /**
     * return empty string the string is null
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param str
     *            The string to split String
     * @param lg
     *            the length to subgstring
     * @return a substring of parameter str.
     */
    public static String substring(String str, int lg) {
        return substring(str, 0, lg);
    }

    /**
     * return empty string the string is null
     *
     * @author Henri Yves AMAIZO $Date: 2002/10/30 23:38:12 $
     * @param str
     *            The string to split String
     * @param start
     *            the location to start
     * @param end
     *            the end location of the substring
     * @return a substring of parameter str.
     */
    public static String substring(String str, int start, int end) {
        if (str == null || str.length() <= start) {
            return null;
        } else if (str.length() >= end) {
            return str.substring(start, end);
        } else {
            return str.substring(start);
        }
    }

    public static void main(String[] args) {
        /*
         * String buf="SX1 in ('1','2','3','4','5','6','7') and SX2 in ('3','7')
         * and SX5 in ('3','4') and SX6 in ('2')"; List
         * lt=StringUtil.string2List(buf,"and"); if(lt!=null && lt.size()>0){
         * for(int i=0;i<lt.size();i++){ String condi=(String)lt.get(i); List
         * list=StringUtil.string2List(condi,"in"); if(list!=null){ String
         * sxname=(String)list.get(0); String sxvalue=(String)list.get(1);
         * sxvalue=StringUtil.substring(sxvalue,1,sxvalue.length()-1);
         * sxvalue=StringUtil.replace(sxvalue,"'","");
         *  } } }
         *
         * String ddd="ABCDEFf"; ddd=ddd.toLowerCase() ;
         *
         */
        /*
         * String str = " from #VW_SL_SDXDetailD# as vw "; List list =
         * StringUtil.string2List(str, "#"); if (list != null && list.size() >
         * 0) { for (int i = 0; i < list.size(); i++) {
         *  } }
         */
        String t = StringUtil.substring("'aaa'", 1, "'aaa'".length() - 1);


    }

    /**
     * 生成uuid
     *
     * @return 32位长的字符串型uuid
     */
    public static String generateUuid() {
        // 本地生成uuid
        return LocalUuidGenerator.generateUuid();
    }

    /**
     * 字符串是否为null或者空字符串("")
     *
     * @param s
     * @return
     */
    public static boolean isEmpty(String s) {
        if (s == null) {
            return true;
        }
        if (s.length() == 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取一个字符串的boolean值
     *
     * @param theString
     * @return
     */
    public static boolean booleanValueOf(String theString) {
        if (theString == null) {
            return false;
        }

        theString = theString.trim().toLowerCase();

        List<String> trueValues = Arrays.asList(new String[]{"1", "y", "yes",
                    "t", "true", "on"});
        List<String> falseValues = Arrays.asList(new String[]{"", "0", "n",
                    "no", "f", "false", "off"});

        if (trueValues.indexOf(theString) != -1) {
            return true;
        }
        if (falseValues.indexOf(theString) != -1) {
            return false;
        }

        throw new IllegalArgumentException("无法解析传入的字符串为boolean值(" + theString
                + ")");
    }

    /**
     * 传入select语句中的参数值格式化并返回
     *
     * @author mashiqiong Date:2011-12-24
     */
    public static String formatSelectSqlString(String sql) {
        if (sql == null) {
            return sql;
        }
        return formatStringTrim(sql).replaceAll("　", "").replaceAll("'", "''").replaceAll("\\[", "\\[\\[\\]").replaceAll("%", "[%]");
    }

    /**
     * 将参数的左右空格除去后返回，主要是为了去除全角空格
     *
     * @author mashiqiong Date:2011-12-24
     */
    public static String formatStringTrim(String str) {
        if (str == null) {
            return str;
        }
        String str2 = str.trim();
        if (str2.endsWith("　"))// 如果最后一个为全角空格则切掉
        {
            str2 = str2.substring(0, str2.length() - 1);
        }
        if (str2.startsWith("　"))// 如果第一个为全角空格则切掉
        {
            str2 = str2.substring(1, str2.length());
        }
        return str2;
    }
}
